package com.qys.livesMall.app.user.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qys.livesMall.app.user.event.AppUserWithdrawalEvent;
import com.qys.livesMall.app.user.event.UserRechargeEvent;
import com.qys.livesMall.app.user.mapper.*;
import com.qys.livesMall.app.user.model.dto.app.AppUserApplyWithdrawalDTO;
import com.qys.livesMall.app.user.model.dto.app.AppUserRechargeDTO;
import com.qys.livesMall.app.user.model.dto.app.AppUserWithdrawalsDTO;
import com.qys.livesMall.app.user.model.dto.rw.AuditRw;
import com.qys.livesMall.app.user.model.dto.sys.*;
import com.qys.livesMall.app.user.model.entity.*;
import com.qys.livesMall.app.user.model.vo.WithdrawalsStatisticsVO;
import com.qys.livesMall.app.user.model.vo.app.WithdrawalsConfigVO;
import com.qys.livesMall.app.user.model.vo.sys.*;
import com.qys.livesMall.app.user.service.*;
import com.qys.livesMall.app.user.utils.IpLocation;
import com.qys.livesMall.app.user.utils.IpUtils;
import com.qys.livesMall.app.user.utils.PasswordUtil;
import com.qys.livesMall.cache.utils.CacheUtils;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.exception.enums.ExceptionEnum;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.finance.common.Constant;
import com.qys.livesMall.finance.common.FinanceLockPrefix;
import com.qys.livesMall.finance.enums.AccountBusinessTypeEnum;
import com.qys.livesMall.finance.enums.AccountTradeTypeEnum;
import com.qys.livesMall.finance.enums.AccountTypeEnum;
import com.qys.livesMall.finance.enums.FinanceMessageEnum;
import com.qys.livesMall.finance.model.dto.AccountHandle;
import com.qys.livesMall.finance.model.dto.FinancePayDTO;
import com.qys.livesMall.finance.model.entity.user.FinanceUserAccount;
import com.qys.livesMall.finance.service.FinanceBusinessService;
import com.qys.livesMall.finance.service.FinanceUserAccountDetailService;
import com.qys.livesMall.finance.service.FinanceUserAccountService;
import com.qys.livesMall.finance.util.BusinessNoUtil;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.framework.view.BaseQuery;
import com.qys.livesMall.system.model.entity.H2Channel;
import com.qys.livesMall.system.service.IH2SysConfigService;
import com.qys.livesMall.system.service.SysH2ChannelService;
import com.qys.livesMall.system.source.domain.vo.dict.DictVO;
import com.qys.livesMall.system.source.service.ISysDictTypeService;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户充值 服务实现类
 * </p>
 *
 * @author dp
 * @since 2023-04-27
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class H2AppUserRechargeWithdrawalsServiceImpl extends ServiceImpl<H2AppUserRechargeWithdrawalsMapper,
        H2AppUserRechargeWithdrawals> implements IH2AppUserRechargeWithdrawalsService {

    private final H2AppUserMapper appUserMapper;
    private final IH2AppUserService ih2AppUserService;
    private final IH2SysConfigService sysConfigService;
    private final ApplicationContext applicationContext;
    private final FinanceBusinessService financeBusinessService;
    private final UserStatisticsInfoService userStatisticsInfoService;

    private final UserStatisticsInfoMapper userStatisticsInfoMapper;

    private final H2AppUserBankMapper h2AppUserBankMapper;

    private final FinanceUserAccountService financeUserAccountService;

    private final FinanceUserAccountDetailService financeUserAccountDetailService;

    private final ISysDictTypeService dictTypeService;

    private final SysH2ChannelService sysH2ChannelService;
    @Resource
    private AppUserLevelService appUserLevelService;
    @Resource
    private UserRewardConfigService userRewardConfigService;
    @Resource
    private UserRewardHistoryService userRewardHistoryService;
    @Resource
    private IpOperateStatisticsService ipOperateStatisticsService;
    @Resource
    private AppUserRelationService relationService;
    @Resource
    private  CacheUtils cacheUtils;
    @Override
    public void recharge(AppUserRechargeDTO rechargeDTO) {
        log.info("用户充值余额信息:{},用户id:{}", rechargeDTO, SecurityUtils.getUserId());

        H2AppUser appUser = appUserMapper.selectById(SecurityUtils.getUserId());
        if (null == appUser) {
            throw new QysException(MessageUtils.message("re.login"));
        }
        H2AppUserBank h2AppUserBank = h2AppUserBankMapper.selectById(rechargeDTO.getId());
        if (null == h2AppUserBank) {
            log.error("查询用户银行卡信息出错: {}", rechargeDTO.getId());
            throw new QysException(MessageUtils.message("bank.no.blank"));
        }
        H2AppUserRechargeWithdrawals userRecharge = new H2AppUserRechargeWithdrawals();
        BeanUtils.copyProperties(rechargeDTO, userRecharge);
        userRecharge.setId(null);
        userRecharge.setUserId(String.valueOf(SecurityUtils.getUserId()));
        userRecharge.setUserName(SecurityUtils.getUsername());
        userRecharge.setRechargeType((byte) 0);
        userRecharge.setSource((byte) 0);
        userRecharge.setAuditType((byte) 0);
        userRecharge.setCreateTime(LocalDateTime.now());
        userRecharge.setAvatar(appUser.getAvatar());
        userRecharge.setUserSource(Byte.parseByte(String.valueOf(appUser.getUserSysType())));
        userRecharge.setType(AccountBusinessTypeEnum.RECHARGE.getType());
        userRecharge.setAmount(rechargeDTO.getAmount().setScale(4, RoundingMode.HALF_DOWN));
        userRecharge.setOrderNo(BusinessNoUtil.get(AccountBusinessTypeEnum.RECHARGE));
        userRecharge.setChannelId(rechargeDTO.getChannelId());
        userRecharge.setRechargeName(SecurityUtils.getUsername());
        userRecharge.setBankNo(h2AppUserBank.getBankNo());
        userRecharge.setPaymentMethod(h2AppUserBank.getType());
        FinanceUserAccount financeUserAccount = financeUserAccountService.get(Long.valueOf(appUser.getId()));
        if (null != financeUserAccount){
            userRecharge.setAmountBeforeChange(financeUserAccount.getAvailableBalance());
        }
        //银行卡
        if (rechargeDTO.getBankType() == 0) {
            userRecharge.setPaymentMethod((byte) 0);
            //userRecharge.setRateAmount(rechargeDTO.getAmount().divide(rechargeDTO.getExchangeRate(), 4, RoundingMode.HALF_DOWN));
        }
        //USDT BIT
        else {
            userRecharge.setPaymentMethod(rechargeDTO.getBankType());
            //userRecharge.setRateAmount(rechargeDTO.getAmount());
        }

        //转账
        FinancePayDTO payDTO = new FinancePayDTO();
        payDTO.setUserId(Long.valueOf(userRecharge.getUserId()));
        payDTO.setBusinessNo(userRecharge.getOrderNo());
        payDTO.setAmountIncurred(userRecharge.getAmount());
        payDTO.setBusinessType(AccountBusinessTypeEnum.RECHARGE_APPLY_FOR);
        financeBusinessService.pay(payDTO);
        if (!payDTO.getSuccess()) {
            throw new QysException(payDTO.getMessage());
        }
        baseMapper.insert(userRecharge);
    }

    @Override
    public Page<H2AppUserRechargeWithdrawals> page(SysUserRechargePageDTO pageDTO) {

        LambdaQueryWrapper<H2AppUserRechargeWithdrawals> wrapper = Wrappers.lambdaQuery();
        if (pageDTO.getAuditType() != null) {
            wrapper.eq(H2AppUserRechargeWithdrawals::getAuditType, pageDTO.getAuditType());
        }
        if (CollectionUtils.isNotEmpty(pageDTO.getAuditTypes())){
            wrapper.in(H2AppUserRechargeWithdrawals::getAuditType, pageDTO.getAuditTypes());
        }
        if (pageDTO.getUserType() != null) {
            wrapper.eq(H2AppUserRechargeWithdrawals::getUserSource, pageDTO.getUserType());
        }
        if (pageDTO.getPaymentMethod() != null) {
            wrapper.eq(H2AppUserRechargeWithdrawals::getPaymentMethod, pageDTO.getPaymentMethod());
        }
        if (pageDTO.getSource() != null) {
            wrapper.eq(H2AppUserRechargeWithdrawals::getSource, pageDTO.getSource());
        }
        if (pageDTO.getStartTime() != null) {
            wrapper.ge(H2AppUserRechargeWithdrawals::getCreateTime, pageDTO.getStartTime());
        }
        if (pageDTO.getEndTime() != null) {
            wrapper.le(H2AppUserRechargeWithdrawals::getCreateTime, pageDTO.getEndTime());
        }
        if (pageDTO.getType() != null) {
            wrapper.eq(H2AppUserRechargeWithdrawals::getType, pageDTO.getType());
        }
        if (pageDTO.getUserId() != null) {
            wrapper.eq(H2AppUserRechargeWithdrawals::getUserId, pageDTO.getUserId());
        }
        if (StringUtils.isNotBlank(pageDTO.getUserName())) {
            wrapper.like(H2AppUserRechargeWithdrawals::getUserName, pageDTO.getUserName());
        }
        wrapper.orderByDesc(H2AppUserRechargeWithdrawals::getCreateTime);

        return baseMapper.selectPage(new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize()), wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void audit(String id, String remark, BigDecimal amount, int type) {
//        log.info("审核用户申请信息->id{},备注:{}", id, remark);
//
//        H2AppUserRechargeWithdrawals recharge = new H2AppUserRechargeWithdrawals();
//        recharge.setId(id);
//        recharge.setRemark(remark);
//        recharge.setAuditTime(LocalDateTime.now());
//        if (type != 1 & type != 2) {
//            throw new QysException(MessageUtils.message("param.is.error"));
//        }
//        recharge.setAuditType((byte) type);
//        recharge.setRealAmount(amount);
//        baseMapper.updateById(recharge);
//
//        //修改用户余额信息
//        if (type == 1) {
//            recharge = baseMapper.selectById(id);
//
//            SysUserBalanceChangeDTO changeDTO = new SysUserBalanceChangeDTO();
//            changeDTO.setUserId(recharge.getUserId());
//            changeDTO.setId(id);
//            //充值
//            if (recharge.getType() == 0) {
//                changeDTO.setBalanceLogType(UserBalanceLogTypeEnum.RECHARGE);
//                changeDTO.setChangeAmount(amount);
//            }
//            //提现
//            else {
//                changeDTO.setBalanceLogType(UserBalanceLogTypeEnum.WITHDRAWALS);
//                changeDTO.setChangeAmount(recharge.getRealAmount().multiply(new BigDecimal("-1")));
//            }
//            appUserBalanceService.changeUserBalance(changeDTO);
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R auditPass(AuditRw auditRw) {
        synchronized (auditRw.getId()) {
            H2AppUserRechargeWithdrawals rw = getById(auditRw.getId().toString());
            if (rw == null) {
                throw new QysException(ExceptionEnum.PARAM_IS_ERROR);
                //todo
//                return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_FIND_ORDER);
//                return R.fail();
            }
            //提现不填实到金额
            if (Objects.equals(AccountBusinessTypeEnum.WITHDRAWAL.getType(), rw.getType())) {
                auditRw.setActualArrivalAmount(null);
            }
            if (auditRw.getActualArrivalAmount() != null && auditRw.getActualArrivalAmount().compareTo(new BigDecimal("0")) != 1) {

                throw new QysException(ExceptionEnum.PARAM_IS_ERROR);
            }
            if (!Objects.equals((byte)0, rw.getAuditType())) {
                //todo
                //throw new QysException(ShopMessageEnum.SHOP_ORDER_STATUS_EXCEPTION);
                return R.fail(MessageUtils.message("order.status.exception"));
            }
            //todo
//            rw.setAuditType(ShopConstant.RWStatus.AUDITED);
            rw.setAuditType((byte) 1);
            rw.setRemark(auditRw.getAuditDesc());
            rw.setAuditTime(LocalDateTime.now());
            rw.setOperator(SecurityUtils.getUsername());
            if (auditRw.getActualArrivalAmount() == null) {
                auditRw.setActualArrivalAmount(rw.getAmount());
            }
            rw.setRealAmount(auditRw.getActualArrivalAmount());
            BigDecimal difference = rw.getAmount().subtract(rw.getRealAmount());
            //转账
            FinancePayDTO payDTO = new FinancePayDTO();
            payDTO.setUserId(Long.valueOf(rw.getUserId()));
            payDTO.setBusinessNo(rw.getOrderNo());
            payDTO.setAmountIncurred(rw.getRealAmount());
            payDTO.setDescription(auditRw.getAuditDesc());
            if (Objects.equals(AccountBusinessTypeEnum.RECHARGE.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.RECHARGE);
                if (difference.compareTo(new BigDecimal("0")) > 0) {
                    FinancePayDTO differencePayDTO = new FinancePayDTO();
                    differencePayDTO.setBusinessNo(rw.getOrderNo());
                    differencePayDTO.setAmountIncurred(difference.abs());
                    differencePayDTO.setDescription("申请与实际差额");
                    differencePayDTO.setBusinessType(AccountBusinessTypeEnum.RECHARGE_DIFFERENCE);
                    financeBusinessService.pay(differencePayDTO);

                    if (!differencePayDTO.getSuccess()) {
                        throw new QysException(payDTO.getMessage());
                    }
                } else if (difference.compareTo(new BigDecimal("0")) > 0) {
                    FinancePayDTO differencePayDTO = new FinancePayDTO();
                    differencePayDTO.setBusinessNo(rw.getOrderNo());
                    differencePayDTO.setAmountIncurred(difference.abs());
                    differencePayDTO.setDescription("申请与实际差额");
                    differencePayDTO.setBusinessType(AccountBusinessTypeEnum.RECHARGE_APPLY_FOR);
                    financeBusinessService.pay(differencePayDTO);

                    if (!differencePayDTO.getSuccess()) {
                        throw new QysException(payDTO.getMessage());
                    }
                }
            } else if (Objects.equals(AccountBusinessTypeEnum.WITHDRAWAL.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.WITHDRAWAL);
            } else {
                payDTO.setMessage(FinanceMessageEnum.BUSINESS_TYPE_ERROR);
            }
            financeBusinessService.pay(payDTO);

            if (!payDTO.getSuccess()) {
                throw new QysException(payDTO.getMessage());
            }
            UserStatisticsInfo userStatisticsInfo = userStatisticsInfoService.selectByUserId(Long.valueOf(rw.getUserId()));
            if (null != userStatisticsInfo) {
                if (Objects.equals(AccountBusinessTypeEnum.RECHARGE.getType(), rw.getType())) {
                    rw.setNum(userStatisticsInfo.getRechargeNumber() + 1);
                } else {
                    rw.setNum(userStatisticsInfo.getWithdrawalNumber() + 1);
                }
            } else {
                if (Objects.equals(AccountBusinessTypeEnum.RECHARGE.getType(), rw.getType())) {
                    rw.setNum(1);
                } else {
                    rw.setNum(1);
                }
            }
            baseMapper.updateById(rw);

            if (Objects.equals(AccountBusinessTypeEnum.RECHARGE.getType(), rw.getType())) {
                try {
                    for (int i = 0; i < 5; i++) {
                        boolean isLock = cacheUtils.getLock(FinanceLockPrefix.RECHARGE_AUDITPASS_LOCK+rw.getUserId(), CacheUtils.LOCK_WAIT_TIME_60_SECONDS);
                        if (isLock){
                            this.userReward(Long.valueOf(rw.getUserId()), rw.getRealAmount());
                            break;
                        }else {
                            Thread.sleep(2000);
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }finally{
                    //释放锁
                    cacheUtils.releaseLock(FinanceLockPrefix.RECHARGE_AUDITPASS_LOCK+rw.getUserId());
                }
            }
            UserRechargeDTO userRechargeDTO = new UserRechargeDTO();
            userRechargeDTO.setRealAmount(rw.getRealAmount());
            userRechargeDTO.setUserId(Long.valueOf(rw.getUserId()));
            userRechargeDTO.setType(rw.getType());
            applicationContext.publishEvent(new UserRechargeEvent(userRechargeDTO));
            return R.ok();
        }
    }
    public void userReward(Long userId, BigDecimal realAmount){
        //邀请奖励
        ih2AppUserService.InvitationRewards(userId);
        //充值返现
        this.rechargeCashBack(userId, realAmount);
    }
    /**
     *  充值返现
     * @param userId
     */
    private void rechargeCashBack(Long userId, BigDecimal realAmount) {
        List<UserRewardConfig> userRewardConfigs = userRewardConfigService.list();
        if (CollectionUtils.isEmpty(userRewardConfigs)){
            return;
        }
        Map<Integer,List<UserRewardConfig>> map =userRewardConfigs.stream().collect(Collectors.groupingBy(UserRewardConfig::getAwardType));
        //首充返现
        if (null != map.get(4)){
            List<UserRewardConfig> firstCharge=map.get(4);
            Integer rechargeCount= baseMapper.getRechargeCount(userId);
            if (rechargeCount == 1){
                List<UserRewardHistory> list=userRewardHistoryService.getUserRewardHistory(userId,AccountBusinessTypeEnum.USER_RECHARGE_FIRST_RETURN_COST.getType(),null);
                if (CollectionUtils.isEmpty(list)){
                    ih2AppUserService.transferAccounts(userId,AccountBusinessTypeEnum.USER_RECHARGE_FIRST_RETURN_COST,realAmount.multiply(firstCharge.get(0).getAwardUnit().divide(new BigDecimal(100))).setScale(2),firstCharge.get(0).getConId());
                }
            }
        }
        //充值返现
        if (null == map.get(3)){
            return;
        }
        List<UserRewardConfig> rechargeCashBack=map.get(3);
        for (int i = 0; i < rechargeCashBack.size(); i++) {
            JSONObject json = JSONObject.parseObject(rechargeCashBack.get(i).getAwardCondition());
            BigDecimal minPoint=  json.get("minPoint")==null?null:new BigDecimal((Integer) json.get("minPoint"));
            BigDecimal maxPoint=  json.get("maxPoint")==null?null:new BigDecimal((Integer) json.get("maxPoint"));
            if (minPoint == null && maxPoint==null){
               continue;
            }
            //排除实际金额比返现最小金额 还要小的
            if (null != minPoint && minPoint.compareTo(realAmount) == 1){
                continue;
            }
            //排除实际金额比返现最大金额 还要大的和等于的
            if (null != maxPoint && maxPoint.compareTo(realAmount) < 1){
                continue;
            }
            if (StringUtils.isBlank(rechargeCashBack.get(i).getAwardAmount()) || rechargeCashBack.get(i).getAwardAmount().equals("1")){
                ih2AppUserService.transferAccounts(userId,AccountBusinessTypeEnum.USER_RECHARGE_RETURN_COST,rechargeCashBack.get(i).getAwardUnit(),rechargeCashBack.get(i).getConId());
            }else {
                //百分比
                ih2AppUserService.transferAccounts(userId,AccountBusinessTypeEnum.USER_RECHARGE_RETURN_COST,realAmount.multiply(rechargeCashBack.get(i).getAwardUnit().divide(new BigDecimal(100))).setScale(2),rechargeCashBack.get(i).getConId());
            }
         break;
        }
    }


    @Override
    public R auditNoPass(AuditRw auditRw) {
        synchronized (auditRw.getId()) {
            H2AppUserRechargeWithdrawals rw = getById(auditRw.getId());
            if (rw == null) {
                //todo
                return R.fail();
            }
            if (!Objects.equals(rw.getAuditType(), (byte)0)){
                return R.fail(MessageUtils.message("order.status.exception"));
            }
            rw.setAuditType(auditRw.getType());
            rw.setRemark(auditRw.getAuditDesc());
            rw.setAuditTime(LocalDateTime.now());
            rw.setOperator(SecurityUtils.getUsername());

            //转账
            FinancePayDTO payDTO = new FinancePayDTO();
            payDTO.setUserId(Long.valueOf(rw.getUserId()));
            payDTO.setBusinessNo(rw.getOrderNo());
            payDTO.setAmountIncurred(rw.getAmount());
            payDTO.setDescription(auditRw.getAuditDesc());
            //处理店铺余额

            payDTO.setDescription(auditRw.getAuditDesc());
            if (Objects.equals(AccountBusinessTypeEnum.RECHARGE.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.RECHARGE_CANCEL);
                financeBusinessService.pay(payDTO);
                if (payDTO.getSuccess()){
                    AccountHandle handle=new AccountHandle();
                    handle.setUserId(payDTO.getUserId());
                    handle.setPayMethod(Constant.PayMethod.BALANCE);
                    handle.setTradeTypeEnum(AccountTradeTypeEnum.OUT);
                    handle.setAccountType(AccountTypeEnum.USER_ACCOUNT.getType());
                    handle.setAmountIncurred(new BigDecimal("0"));
                    handle.setFreezeAmount(payDTO.getAmountIncurred());
                    handle.setBusinessNo(payDTO.getBusinessNo());
                    handle.setBusinessType(payDTO.getBusinessType());
                    handle.setDescription(payDTO.getDescription());
                    //查询余额
                    FinanceUserAccount account=financeUserAccountService.get(payDTO.getUserId());
                    financeUserAccountDetailService.addOtherLog(handle,account);
                }
                //不处理
            } else if (Objects.equals(AccountBusinessTypeEnum.WITHDRAWAL.getType(), rw.getType())) {
                payDTO.setBusinessType(AccountBusinessTypeEnum.WITHDRAWAL_CANCEL);
                financeBusinessService.pay(payDTO);
            }

            if (!payDTO.getSuccess()) {
                throw new QysException(payDTO.getMessage());
            }
            updateById(rw);
            if (rw.getType().equals(AccountBusinessTypeEnum.WITHDRAWAL.getCode())) {
                AppUserApplyWithdrawalDTO appUserApplyRechargeDTO = new AppUserApplyWithdrawalDTO();
                appUserApplyRechargeDTO.setUserId(rw.getUserId());
                appUserApplyRechargeDTO.setAmount(rw.getAmount());
                appUserApplyRechargeDTO.setType(2);
                applicationContext.publishEvent(new AppUserWithdrawalEvent(appUserApplyRechargeDTO));
            }
            return R.ok();
        }
    }

    @Override
    @Transactional
    public void withdrawals(AppUserWithdrawalsDTO withdrawalsDTO) {
        log.info("用户提现余额信息:{},用户id:{}", withdrawalsDTO, SecurityUtils.getUserId());

        H2AppUser appUser = appUserMapper.selectById(SecurityUtils.getUserId());
        if (null == appUser) {
            throw new QysException(MessageUtils.message("re.login"));
        }
        if (appUser.getStatus() == 1) {
            throw new QysException(MessageUtils.message("user.freeze.centre"));
        }

        //校验用户密码信息
        checkUserPassword(appUser, withdrawalsDTO.getPassword());

        FinanceUserAccount financeUserAccount = financeUserAccountService.get(Long.valueOf(appUser.getId()));
        if (null == financeUserAccount) {
            throw new QysException(MessageUtils.message("financial.balance.not.match"));
        }
        checkUserwithdrawals(Long.valueOf(appUser.getId()),withdrawalsDTO.getAmount());

        H2AppUserRechargeWithdrawals userRecharge = new H2AppUserRechargeWithdrawals();
        BeanUtils.copyProperties(withdrawalsDTO, userRecharge);
        userRecharge.setType(AccountBusinessTypeEnum.WITHDRAWAL.getType());

        //银行卡信息

        H2AppUserBank h2AppUserBank = h2AppUserBankMapper.selectById(withdrawalsDTO.getId());
        if (null == h2AppUserBank) {
            log.error("查询用户银行卡信息出错: {}", withdrawalsDTO.getId());
            throw new QysException(MessageUtils.message("bank.no.blank"));
        }

        H2AppUserRechargeWithdrawals withdrawals = new H2AppUserRechargeWithdrawals();
        BeanUtils.copyProperties(h2AppUserBank,withdrawals);
        if (h2AppUserBank.getType()==(byte)1){
            withdrawals.setBankAddress(h2AppUserBank.getBankNo());
        }
        withdrawals.setId(null);
        withdrawals.setRechargeName(h2AppUserBank.getBankUserName());
        withdrawals.setUserId(appUser.getId());
        withdrawals.setUserName(appUser.getNickName());
        withdrawals.setAmount(withdrawalsDTO.getAmount().setScale(2, RoundingMode.HALF_EVEN));
        withdrawals.setCountry(withdrawalsDTO.getCountry());
        withdrawals.setExchangeRate(withdrawalsDTO.getExchangeRate());
        withdrawals.setAuditType((byte) 0);
        withdrawals.setAvatar(appUser.getAvatar());
        withdrawals.setUserSource(Byte.parseByte(String.valueOf(appUser.getUserSysType())));
        withdrawals.setType(AccountBusinessTypeEnum.WITHDRAWAL.getType());
        withdrawals.setCreateTime(LocalDateTime.now());
        withdrawals.setPaymentMethod(h2AppUserBank.getType());
        withdrawals.setOrderNo(BusinessNoUtil.get(AccountBusinessTypeEnum.WITHDRAWAL));
        withdrawals.setChannelId(withdrawalsDTO.getChannelId());
        if (null != financeUserAccount){
            withdrawals.setAmountBeforeChange(financeUserAccount.getAvailableBalance());
        }
        //银行卡
//        if (h2AppUserBank.getType() == 0) {
//            addBankInfo(h2AppUserBank, withdrawals);
//        }
//        //USDT BIT
//        else {
//            withdrawals.setRealAmount(withdrawalsDTO.getAmount());
//        }

        baseMapper.insert(withdrawals);
        //扣款
        FinancePayDTO payDTO = new FinancePayDTO();
        payDTO.setUserId(Long.valueOf(withdrawals.getUserId()));
        payDTO.setBusinessNo(withdrawals.getOrderNo());
        payDTO.setAmountIncurred(withdrawals.getAmount());
        payDTO.setBusinessType(AccountBusinessTypeEnum.WITHDRAWAL_APPLY_FOR);
        financeBusinessService.pay(payDTO);
        if (!payDTO.getSuccess()) {
            throw new QysException(payDTO.getMessage());
        }
        AppUserApplyWithdrawalDTO appUserApplyRechargeDTO = new AppUserApplyWithdrawalDTO();
        appUserApplyRechargeDTO.setUserId(withdrawals.getUserId());
        appUserApplyRechargeDTO.setAmount(withdrawals.getAmount());
        appUserApplyRechargeDTO.setType(1);
        applicationContext.publishEvent(new AppUserWithdrawalEvent(appUserApplyRechargeDTO));
    }

    private Boolean checkUserwithdrawals(Long userId,BigDecimal amount) {
        WithdrawalsConfigVO withdrawalsConfigVO=getWithdrawalsConfig(userId);
        if (null == withdrawalsConfigVO){
            throw new QysException(MessageUtils.message("用户等级不匹配"));
        }
        //校验用户提现金额范围
        if (null != withdrawalsConfigVO.getMinimumWithdrawal() && withdrawalsConfigVO.getMinimumWithdrawal().compareTo(amount) >0){
            String msg = String.format(MessageUtils.message("sms.user.level.withdrawal.amount"),withdrawalsConfigVO.getMinimumWithdrawal(),withdrawalsConfigVO.getMaximumWithdrawal());
            throw new QysException(MessageUtils.message(msg));
        }
        if (null !=withdrawalsConfigVO.getMaximumWithdrawal() && withdrawalsConfigVO.getMaximumWithdrawal().compareTo(amount) <0 ){
            String msg = String.format(MessageUtils.message("user.level.withdrawal.amount"), withdrawalsConfigVO.getMinimumWithdrawal(),withdrawalsConfigVO.getMaximumWithdrawal());
            throw new QysException(msg);
        }
        //校验用户当日提现次数
        if (null != withdrawalsConfigVO.getDailyWithdrawal() && withdrawalsConfigVO.getDailyWithdrawal() <= 0){
            throw new QysException(MessageUtils.message("user.level.withdrawal.day.max"));
        }
        return true;
    }

    @Override
    public List<H2AppUserRechargeWithdrawals> listAgreeByIds(List<Long> ids) {
        LambdaQueryWrapper<H2AppUserRechargeWithdrawals> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(H2AppUserRechargeWithdrawals::getAuditType, 1);
        queryWrapper.in(H2AppUserRechargeWithdrawals::getUserId, ids);
        return list(queryWrapper);
    }

    @Override
    public List<H2AppUserRechargeWithdrawals> getlistWaitByIds(List<Long> ids) {
        LambdaQueryWrapper<H2AppUserRechargeWithdrawals> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(H2AppUserRechargeWithdrawals::getAuditType, 0);
        queryWrapper.eq(H2AppUserRechargeWithdrawals::getType, AccountBusinessTypeEnum.WITHDRAWAL.getType());
        queryWrapper.in(CollectionUtils.isNotEmpty(ids),H2AppUserRechargeWithdrawals::getUserId, ids);
        return list(queryWrapper);
    }

    @Override
    public Page<RechargStatisticsVO> rechargePage(RechargStatisticsPage pageDTO) {
        if (StringUtils.isNotBlank(pageDTO.getUserDirectPush()) || StringUtils.isNotBlank(pageDTO.getUser3rdGeneration()) || StringUtils.isNotBlank(pageDTO.getUserUnderUmbrella())){
            List<Long> userIds=null;
            if (StringUtils.isNotBlank(pageDTO.getUserDirectPush())){
                //直推
                userIds=relationService.getLowerLevels(pageDTO.getUserDirectPush(),1);
            }else if (StringUtils.isNotBlank(pageDTO.getUser3rdGeneration())){
                //三代
                userIds=relationService.getLowerLevels(pageDTO.getUser3rdGeneration(),Arrays.asList(1,2,3));
            }else if (StringUtils.isNotBlank(pageDTO.getUserUnderUmbrella())){
                //伞下
                userIds=relationService.getGreaterLevels(pageDTO.getUserUnderUmbrella(),0);
            }
            //查询真实用户，状态正常，充值用户
            if (CollectionUtils.isNotEmpty(userIds)){
                userIds=relationService.getValidUser(userIds);
            }
            if (CollectionUtils.isEmpty(userIds)){
                return new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
            }
            pageDTO.setUserIds(userIds);
        }
        Page<RechargStatisticsVO> page = new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
        page = baseMapper.rechargePage(page, pageDTO);
        List<DictVO> dictVOS=dictTypeService.selectDictDataByType("payment_method","en_US");
        Map<String,String> dictVOMap=dictVOS.stream().collect(Collectors.toMap(DictVO::getDictValue,DictVO::getDictLabel));

        List<H2Channel> h2Channels = sysH2ChannelService.list();
        Map<Integer,String> channelMap=h2Channels.stream().collect(Collectors.toMap(H2Channel::getId,H2Channel::getChannelName));
        Map<String,Integer> ipMap=new HashMap<>();
        if (CollectionUtils.isNotEmpty(page.getRecords())){
            List<String> registerIps = page.getRecords().stream().map(RechargStatisticsVO::getRegisterIp).collect(Collectors.toList());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(registerIps)){
                List<IpOperateStatistics> ipOperateStatistics = ipOperateStatisticsService.getbyIps(registerIps,0);
                ipMap=ipOperateStatistics.stream().collect(Collectors.toMap(IpOperateStatistics::getIp,IpOperateStatistics::getNum));
            }
        }
        Map<String, Integer> finalIpMap = ipMap;
        page.getRecords().forEach(e -> {
            if (null != e.getTeamId()){
                H2AppUser h2AppUser=ih2AppUserService.getById(e.getTeamId());
                e.setAgentName(h2AppUser.getNickName());
            }
            if (null != e.getPaymentMethod()){
                e.setPaymentMethodStr(dictVOMap.get(e.getPaymentMethod().toString()));
            }
            if (null != e.getPaymentMethod()){
                e.setChannelName(channelMap.get(e.getChannelId()));
            }
            if (null != e.getRegisterIp() && StringUtils.isBlank(e.getCountry()) ){
                IpLocation ipLocation= IpUtils.getLocation(e.getRegisterIp());
                e.setCountry(ipLocation.getCountry());
            }
            if (StringUtils.isNotBlank(e.getRegisterIp())){
                e.setIpRegisterNumber(finalIpMap.get(e.getRegisterIp()));
            }
        });
        return page;
    }

    @Override
    public Page<WithdrawalsStatisticsVO> withdrawalsPage(WithdrawalsStatisticsPage pageDTO) {
        Page<WithdrawalsStatisticsVO> page = new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
        if (StringUtils.isNotBlank(pageDTO.getUserDirectPush()) || StringUtils.isNotBlank(pageDTO.getUser3rdGeneration()) || StringUtils.isNotBlank(pageDTO.getUserUnderUmbrella())){
            List<Long> userIds=null;
            if (StringUtils.isNotBlank(pageDTO.getUserDirectPush())){
                //直推
                userIds=relationService.getLowerLevels(pageDTO.getUserDirectPush(),1);
            }else if (StringUtils.isNotBlank(pageDTO.getUser3rdGeneration())){
                //三代
                userIds=relationService.getLowerLevels(pageDTO.getUser3rdGeneration(),Arrays.asList(1,2,3));
            }else if (StringUtils.isNotBlank(pageDTO.getUserUnderUmbrella())){
                //伞下
                userIds=relationService.getGreaterLevels(pageDTO.getUserUnderUmbrella(),0);
            }
            //查询真实用户，状态正常，充值用户
            if (CollectionUtils.isNotEmpty(userIds)){
                userIds=relationService.getValidUser(userIds);
            }
            if (CollectionUtils.isEmpty(userIds)){
                return new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
            }
            pageDTO.setUserIds(userIds);
        }
        Page<WithdrawalsStatisticsVO> resultPage = baseMapper.withdrawalsPage(page, AccountBusinessTypeEnum.WITHDRAWAL.getCode(), pageDTO);

        Map<String,Integer> ipMap=new HashMap<>();
        if (CollectionUtils.isNotEmpty(page.getRecords())){
            List<String> registerIps = page.getRecords().stream().map(WithdrawalsStatisticsVO::getRegisterIp).collect(Collectors.toList());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(registerIps)){
                List<IpOperateStatistics> ipOperateStatistics = ipOperateStatisticsService.getbyIps(registerIps,0);
                ipMap=ipOperateStatistics.stream().collect(Collectors.toMap(IpOperateStatistics::getIp,IpOperateStatistics::getNum));
            }
        }
        Map<String, Integer> finalIpMap = ipMap;
        for (WithdrawalsStatisticsVO record : resultPage.getRecords()) {
            if (record.getFirstCharge() != null) {
                Duration duration = Duration.between(record.getFirstCharge(), LocalDateTime.now());
                //首充天数计算
                int days = (int) duration.toDays();
                record.setFirstChargeDay(days==0?1:days);
            }
            if (StringUtils.isNotBlank(record.getRegisterIp())){
                record.setSameRegisterIpNum(finalIpMap.get(record.getRegisterIp()));
            }

            H2AppUser superiorAppUser = ih2AppUserService.getById(record.getSuperiorId());
            if (null != superiorAppUser){
                record.setSuperiorId(superiorAppUser.getUserRandomId());
            }
        }
        return resultPage;
    }

    @Override
    public List<H2AppUserRechargeWithdrawals> getYesterday() {
        return baseMapper.getYesterday();
    }

    @Override
    public Integer WithdrawalstByUserIds(List<String> list, int num) {
        return baseMapper.WithdrawalstByUserIds(list, num);
    }

    @Override
    public BigDecimal getAuditWithdrawal(SysHomeStatisticsDTO dto) {
        return baseMapper.getAuditWithdrawal(dto);
    }

    @Override
    public BigDecimal getInitiateWithdrawal(Integer userSysType) {
        return baseMapper.getInitiateWithdrawal(userSysType);
    }

    @Override
    public List<H2AppUserRechargeWithdrawals> getTodayData(Integer userSysType) {
        return baseMapper.getTodayData(userSysType);
    }

    @Override
    public Integer gettotalRechargePeoplecount(Integer userSysType) {
        return baseMapper.gettotalRechargePeoplecount(userSysType);
    }

    @Override
    public BigDecimal getAuditWithdrawalByUserids(List<Long> userids) {
        return baseMapper.getAuditWithdrawalByUserids(userids);
    }

    @Override
    public BigDecimal getAuditShopWithdrawalByUserids(List<Long> userids) {
        return baseMapper.getAuditShopWithdrawalByUserids(userids);
    }

    @Override
    public List<Long> getChildInfo(List<Long> userIdList) {
        return baseMapper.getChildInfo(userIdList);
    }

    @Override
    public BigDecimal getRechargeAmount(List<Long> userIdAll) {
        return baseMapper.getRechargeAmount(userIdAll);
    }

    @Override
    public BigDecimal getthreewithdrawalAmount(List<Long> userIdAll) {
        return baseMapper.getthreewithdrawalAmount(userIdAll);
    }

    @Override
    public BigDecimal getTeamRechargeAmount(List<String> subordinateUserIds) {
        return baseMapper.getTeamRechargeAmount(subordinateUserIds);
    }

    @Override
    public RechargStatisticsStateVO rechargeState(RechargStatisticsPage pageDTO) {
        RechargStatisticsStateVO rechargStatisticsStateVO=new RechargStatisticsStateVO();
        if (StringUtils.isNotBlank(pageDTO.getUserDirectPush()) || StringUtils.isNotBlank(pageDTO.getUser3rdGeneration()) || StringUtils.isNotBlank(pageDTO.getUserUnderUmbrella())){
            List<Long> userIds=null;
            if (StringUtils.isNotBlank(pageDTO.getUserDirectPush())){
                //直推
                userIds=relationService.getLowerLevels(pageDTO.getUserDirectPush(),1);
            }else if (StringUtils.isNotBlank(pageDTO.getUser3rdGeneration())){
                //三代
                userIds=relationService.getLowerLevels(pageDTO.getUser3rdGeneration(),Arrays.asList(1,2,3));
            }else if (StringUtils.isNotBlank(pageDTO.getUserUnderUmbrella())){
                //伞下
                userIds=relationService.getGreaterLevels(pageDTO.getUserUnderUmbrella(),0);
            }
            //查询真实用户，状态正常，充值用户
            if (CollectionUtils.isNotEmpty(userIds)){
                userIds=relationService.getValidUser(userIds);
            }
            if (CollectionUtils.isEmpty(userIds)){
                return rechargStatisticsStateVO;
            }
            pageDTO.setUserIds(userIds);
        }
        List<RechargStatisticsVO> list= baseMapper.rechargeList(pageDTO);
        if (CollectionUtils.isEmpty(list)){
            return rechargStatisticsStateVO;
        }

        //银行卡
        long bankCardAgree =list.stream().filter(a-> a.getPaymentMethod() ==0 && a.getAuditType().intValue()==1).count();
        rechargStatisticsStateVO.setBankCardAgree((int) bankCardAgree);
        long BankCardRefuse =list.stream().filter(a-> a.getPaymentMethod() ==0 && a.getAuditType().intValue()==2).count();
        rechargStatisticsStateVO.setBankCardRefuse((int) BankCardRefuse);
        long BankCardWait =list.stream().filter(a-> a.getPaymentMethod() ==0 && a.getAuditType().intValue()==0).count();
        rechargStatisticsStateVO.setBankCardWait((int) BankCardWait);

        //USDT
        long UsdtAgree =list.stream().filter(a-> a.getPaymentMethod() ==1 && a.getAuditType().intValue()==1).count();
        rechargStatisticsStateVO.setUsdtAgree((int) UsdtAgree);
        long UsdtRefuse =list.stream().filter(a-> a.getPaymentMethod() ==1 && a.getAuditType().intValue()==2).count();
        rechargStatisticsStateVO.setUsdtRefuse((int) UsdtRefuse);
        long UsdtWait =list.stream().filter(a-> a.getPaymentMethod() ==1 && a.getAuditType().intValue()==0).count();
        rechargStatisticsStateVO.setUsdtWait((int) UsdtWait);
        return rechargStatisticsStateVO;
    }

    @Override
    public List<UserJuniorInfoVO> getJuniorInfo(List<Long> userIds) {
        List<UserJuniorInfoVO> shopJuniorInfoVOS = new ArrayList<>();
        Set<Long> useridAll=new HashSet<>();
        for (Long userId : userIds) {
            UserJuniorInfoVO shopJuniorInfoVO = new UserJuniorInfoVO();
            shopJuniorInfoVO.setUserId(userId);
            //伞下人数
            List<H2AppUser> allIds=relationService.getLowerLevels(userId);
            if (CollectionUtils.isEmpty(allIds)){
                shopJuniorInfoVOS.add(shopJuniorInfoVO);
                continue;
            }
            List<Long> allList = relationService.getGradeValidUser(allIds.stream().map(a->Long.valueOf(a.getId())).collect(Collectors.toList()));
            shopJuniorInfoVO.setAllNumber(allList.size());

//          一代
            List<H2AppUser> rechargeIds=relationService.getLowerLevels(userId,1);
            shopJuniorInfoVO.setRegisterNum((int) rechargeIds.stream().filter(a->a.getStatus()==0 && a.getUserSysType() !=0).count());
            List<Long> rechargeList = relationService.getGradeValidUser(rechargeIds.stream().map(a->Long.valueOf(a.getId())).collect(Collectors.toList()));
            shopJuniorInfoVO.setDirectNum(rechargeList.size());
            useridAll.addAll(rechargeList);
//            二代
            List<H2AppUser> twoUserIds = relationService.getLowerLevels(userId,2);
            if (CollectionUtils.isEmpty(twoUserIds)){
                convertRW(useridAll,shopJuniorInfoVO);
                shopJuniorInfoVOS.add(shopJuniorInfoVO);
                continue;
            }
            shopJuniorInfoVO.setRegisterNum(shopJuniorInfoVO.getRegisterNum()+(int) twoUserIds.stream().filter(a->a.getStatus()==0 && a.getUserSysType() !=0 ).count());
            List<Long> secondRechargeList = relationService.getGradeValidUser(twoUserIds.stream().map(a->Long.valueOf(a.getId())).collect(Collectors.toList()));
            useridAll.addAll(secondRechargeList);
            shopJuniorInfoVO.setSecondGrandNum(secondRechargeList.size());
//            三代
            List<H2AppUser> treeUserIds=relationService.getLowerLevels(userId,3);
            if (CollectionUtils.isNotEmpty(treeUserIds)){
                shopJuniorInfoVO.setRegisterNum(shopJuniorInfoVO.getRegisterNum()+(int) treeUserIds.stream().filter(a->a.getStatus()==0 && a.getUserSysType() !=0).count());
                List<Long> grandChildUserIds = relationService.getGradeValidUser(treeUserIds.stream().map(a->Long.valueOf(a.getId())).collect(Collectors.toList()));
                useridAll.addAll(grandChildUserIds);
                shopJuniorInfoVO.setThirdGrandNum(grandChildUserIds.size());
            }
            convertRW(useridAll,shopJuniorInfoVO);
            shopJuniorInfoVOS.add(shopJuniorInfoVO);
        }
        return shopJuniorInfoVOS;
    }

    @Override
    public WithdrawalsConfigVO getWithdrawalsConfig(Long userId) {
        H2AppUser h2AppUser=ih2AppUserService.getById(userId);
        AppUserLevel appUserLevel=appUserLevelService.getById(h2AppUser.getUserLevelId());
        if (null == appUserLevel){
            return null;
        }
        FinanceUserAccount financeUserAccount = financeUserAccountService.get(userId);
        if (null == financeUserAccount) {
            throw new QysException(MessageUtils.message("financial.balance.not.match"));
        }
        if (financeUserAccount.getAvailableBalance().compareTo(appUserLevel.getKeepAmount()) == -1){
            throw new QysException(MessageUtils.message("user.level.amount"));
        }
        List<H2AppUserRechargeWithdrawals> dayWithdrawals = baseMapper.getDyaWithdrawal(String.valueOf(userId));
        List<H2AppUserRechargeWithdrawals> weekWithdrawal = baseMapper.getWeekWithdrawal(String.valueOf(userId));

        WithdrawalsConfigVO withdrawalsConfigVO=new WithdrawalsConfigVO();
        withdrawalsConfigVO.setMinimumWithdrawal(appUserLevel.getMinimumWithdrawal());
        withdrawalsConfigVO.setMaximumWithdrawal(appUserLevel.getMaximumWithdrawal());

        int week = appUserLevel.getWeeklyWithdrawal()-weekWithdrawal.size();
        int day = appUserLevel.getDailyWithdrawal()-dayWithdrawals.size();

        int num=week>day?day:week;
        withdrawalsConfigVO.setDailyWithdrawal(num);
        return withdrawalsConfigVO;
    }

    @Override
    public Page<AppUserRWRankingVO> rwrankingPage(BaseQuery baseQuery) {
        Page<AppUserRWRankingVO> page = new Page<>(baseQuery.getPageNum(), baseQuery.getPageSize());
        page = baseMapper.rwrankingPage(page, baseQuery);
        return page;
    }

    @Override
    public List<UserRWChannelStatisticsVO> getRWChannelStatistics() {
        LambdaQueryWrapper<H2AppUserRechargeWithdrawals> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.in(H2AppUserRechargeWithdrawals::getAuditType,1,2);
        queryWrapper.in(H2AppUserRechargeWithdrawals::getPaymentMethod,0,1);
        queryWrapper.eq(H2AppUserRechargeWithdrawals::getDeleted,0);
        List<H2AppUserRechargeWithdrawals> list = list(queryWrapper);
        if (CollectionUtils.isEmpty(list)){
            return null;
        }
        List<UserRWChannelStatisticsVO> rwChannelStatisticsVOS=new ArrayList<>();

        Map<String,List<H2AppUserRechargeWithdrawals>> map = list.stream().collect(Collectors.groupingBy(a->a.getPaymentMethod()+"_"+a.getType()));
        for (String key:map.keySet()) {
            UserRWChannelStatisticsVO userRWChannelStatisticsVO=new UserRWChannelStatisticsVO();
            String[] arr=key.split("_");
            if (arr[1].equals("re")){
                userRWChannelStatisticsVO.setChannelName(arr[0].equals("0")?"银行卡充值":"USDT充值");
            }else if (arr[1].equals("wl")){
                userRWChannelStatisticsVO.setChannelName(arr[0].equals("0")?"银行卡提现":"USDT提现");
            }
            userRWChannelStatisticsVO.setChannelCategory(arr[0].equals("0")?"银行卡":"USDT");
            List<H2AppUserRechargeWithdrawals> appUserRechargeWithdrawals = map.get(key);
            userRWChannelStatisticsVO.setTotal(appUserRechargeWithdrawals.size());
            long successNum = appUserRechargeWithdrawals.stream().filter(a->String.valueOf(a.getAuditType()).equals("1")).count();
            userRWChannelStatisticsVO.setSuccessNum((int) successNum);
            BigDecimal totalAmount=appUserRechargeWithdrawals.stream().map(H2AppUserRechargeWithdrawals::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            userRWChannelStatisticsVO.setTotalAmount(totalAmount);
            BigDecimal successAmount=appUserRechargeWithdrawals.stream().filter(a->String.valueOf(a.getAuditType()).equals("1") && a.getRateAmount() !=null ).map(H2AppUserRechargeWithdrawals::getRateAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            userRWChannelStatisticsVO.setSuccessAmount(successAmount);

            userRWChannelStatisticsVO.setSuccessRate(String.format("%.2f", userRWChannelStatisticsVO.getSuccessNum() /(float) userRWChannelStatisticsVO.getTotal()));
            rwChannelStatisticsVOS.add(userRWChannelStatisticsVO);
         }
        return rwChannelStatisticsVOS;
    }

    @Override
    public List<H2AppUserRechargeWithdrawals> getYesterdayRwDate(Integer userSysType) {
        return baseMapper.getYesterdayRwDate(userSysType);
    }

    /**
     * 充值和提现
     * @param userIdAll
     * @param shopJuniorInfoVO
     */
    @Override
    public void convertRW(Set<Long> userIdAll, UserJuniorInfoVO shopJuniorInfoVO) {
        if (CollectionUtils.isEmpty(userIdAll)){
            return;
        }
        List<String> userids=userIdAll.stream().map(String::valueOf).collect(Collectors.toList());
        BigDecimal rechargeAmount = this.getTeamRechargeAmount(userids);
        shopJuniorInfoVO.setRechargeAmount(rechargeAmount);

        BigDecimal withdrawalAmount=this.getthreewithdrawalAmount(new ArrayList<>(userIdAll));
        shopJuniorInfoVO.setWithdrawalAmount(withdrawalAmount);
    }

    @Override
    public H2AppUserRechargeWithdrawals getEarliestRechargeBYUserId(Long userId) {
        LambdaQueryWrapper<H2AppUserRechargeWithdrawals> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(H2AppUserRechargeWithdrawals::getUserId,userId);
        queryWrapper.eq(H2AppUserRechargeWithdrawals::getType,AccountBusinessTypeEnum.RECHARGE.getCode());
        queryWrapper.eq(H2AppUserRechargeWithdrawals::getAuditType,1);
        queryWrapper.orderByAsc(H2AppUserRechargeWithdrawals::getAuditTime);
        queryWrapper.last("limit 1");
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 用户提现校验密码信息
     *
     * @param appUser
     * @param password
     */
    private void checkUserPassword(H2AppUser appUser, String password) {
        //未设置密码
        if (StringUtils.isBlank(appUser.getUserWithdrawalPassword())) {
            throw new QysException(MessageUtils.message("set.password"));
        }

        //密码校验
        String inputPwd = PasswordUtil.encrypt(password, appUser.getUserName(), appUser.getSalt());
        if (!Objects.equals(inputPwd, appUser.getUserWithdrawalPassword())) {
            throw new QysException(MessageUtils.message("password.error"));
        }
    }

    private static void addBankInfo(H2AppUserBank h2AppUserBank, H2AppUserRechargeWithdrawals withdrawals) {
        withdrawals.setRechargeName(h2AppUserBank.getUserName());
        withdrawals.setBankName(h2AppUserBank.getBankName());
        withdrawals.setBankNo(h2AppUserBank.getBankNo());

        //银行卡需要计算汇率信息
        withdrawals.setRateAmount(withdrawals.getAmount().multiply(withdrawals.getExchangeRate()).setScale(2, RoundingMode.HALF_EVEN));
    }
}
